#include					<iostream>
#include					"SoundPacket.h"
#include					"recorder.h"

Recorder::Recorder(QObject *parent) : QObject(parent), _frames_per_buffer(240), _num_channels(2), _buffer(20, _frames_per_buffer * _num_channels), _soundBuff(40)
{
  //	_sample_rate = 48000;
	_sample_rate = 44100;
//	_buffer.init(30, _frames_per_buffer * _num_channels);
	qDebug() << "Recorder::Recorder()";
}

Recorder::~Recorder()
{
	if (_stream)
		Pa_CloseStream(_stream);
}

static int					recordCallback( const void *inputBuffer, void *outputBuffer,
                              unsigned long framesPerBuffer,
                              const PaStreamCallbackTimeInfo* timeInfo,
                              PaStreamCallbackFlags statusFlags,
                              void *userData)
{
	Recorder			*listener = reinterpret_cast<Recorder *>(userData);

	return listener->record((const short *) inputBuffer);
}

int						Recorder::getCableDevice()
{
	int numDevices;
	int err;
	numDevices = Pa_GetDeviceCount();
	if( numDevices < 0 )
	{
	    printf( "ERROR: Pa_CountDevices returned 0x%x\n", numDevices );
	    err = numDevices;
		std::cout << Pa_GetErrorText( err ) << std::endl;
		return -1;
	}

	const   PaDeviceInfo *deviceInfo;
	QString driver("CABLE Output (VB-Audio Virtual Cable)");
	for( int i=0; i < numDevices; i++ )
	{
	    deviceInfo = Pa_GetDeviceInfo( i );
		QString device(deviceInfo->name);
		if (device.contains(driver))
			return i;
	}
	return -1;
}

void					Recorder::init()
{
	PaStreamParameters  _inputParameters;

	_inputParameters.device = getCableDevice();
	//_inputParameters.device = Pa_GetDefaultInputDevice();
	if (_inputParameters.device >= 0)
	{
		_inputParameters.channelCount = _num_channels;
		_inputParameters.sampleFormat = paInt16;
		_inputParameters.suggestedLatency = Pa_GetDeviceInfo(_inputParameters.device)->defaultLowInputLatency;
		_inputParameters.hostApiSpecificStreamInfo = NULL;
		int err = Pa_OpenStream(&_stream, &_inputParameters, NULL, _sample_rate, _frames_per_buffer, paClipOff, recordCallback, this);
		std::cout << "[INFO] CABLE Audio driver loaded." << std::endl;
	}
	else
		std::cout << "[CRITICAL] Can't find CABLE Audio Driver." << std::endl;
}

void						Recorder::start()
{
	PaError		err;

	std::cout << "starting audio recording object" << std::endl;
	if (_stream && (err = Pa_IsStreamActive(_stream)) != 1)
	{
		_status = paContinue;
//		_buffer.reset();
		_frameIndex = 0;
		err = Pa_StartStream(_stream);
		std::cout << Pa_GetErrorText( err ) << std::endl;
	}
	else
		std::cout << Pa_GetErrorText( err ) << std::endl;
}

void						Recorder::stop()
{
	_status = paComplete;
	Pa_StopStream(_stream);
}

int							Recorder::record(const short *inputBuffer)
{
	size_t					to_calc = _frames_per_buffer * _num_channels;
	short					*buf = _buffer.get();

	for (size_t i = 0; i < to_calc; i++)
		buf[i] = inputBuffer[i];

	emit newBuffer(buf);
	return (_status);
}

size_t					Recorder::getFPB() const
{
	return _frames_per_buffer;
}

size_t					Recorder::getChannelNB() const
{
	return _num_channels;
}

size_t					Recorder::getSampleRate() const
{
	return _sample_rate;
}

//void					Recorder::read(ISoundPacket *packet)
//{
//	short				*ret = _buffer.read();
//	packet->setData(ret);
//	packet->setFS(_frames_per_buffer);
//	packet->setLen(_frames_per_buffer * _num_channels);
//}

SoundPacket				*Recorder::getSoundPacket()
{
	SoundPacket			*output = _soundBuff.get();
	//SoundPacket			*output = new SoundPacket;

	output->setFS(_frames_per_buffer);
	output->setLen(_frames_per_buffer * _num_channels);
	return output;
}
